package com.qiaofang.applet.service.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.common.context.QfContext;
import com.qiaofang.applet.common.context.QfContextHolder;
import com.qiaofang.applet.common.dto.SmsDto;
import com.qiaofang.applet.common.exception.BusinessException;
import com.qiaofang.applet.common.util.SmsUtil;
import com.qiaofang.applet.constants.SubscribeConstants;
import com.qiaofang.applet.service.member.domain.Member;
import com.qiaofang.applet.service.member.domain.MemberSubscribe;
import com.qiaofang.applet.service.member.repository.MemberSubscribeRepository;
import com.qiaofang.applet.service.member.service.MemberService;
import com.qiaofang.applet.service.member.service.MemberSubscribeService;
import com.qiaofang.applet.service.member.service.dto.MemberSubscribeDetailDto;
import com.qiaofang.applet.service.member.service.dto.MemberSubscribeQueryDto;
import com.qiaofang.applet.service.member.service.dto.MemberSubscribeSaveDto;
import com.qiaofang.applet.service.member.service.dto.UpdateSubscribeStatusDto;
import com.qiaofang.applet.service.member.service.mapstruct.MemberSubscribeMapper;
import com.qiaofang.applet.service.other.domain.Corporation;
import com.qiaofang.applet.service.other.domain.SmsPlatformConfig;
import com.qiaofang.applet.service.other.service.CorporationService;
import com.qiaofang.applet.service.property.domain.FirsthandEstate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by IDEA.
 *
 * @auther Zym.
 * @company qiaofang
 * @date 2020/9/17 19:39
 */
@Slf4j
@Service
public class MemberSubscribeServiceImpl extends MongoBaseService<MemberSubscribe, String> implements MemberSubscribeService {

    private final MemberSubscribeRepository memberSubscribeRepository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private MemberSubscribeMapper memberSubscribeMapper;

    @Autowired
    private MemberService memberService;

    @Autowired
    private CorporationService corporationService;

    @Autowired
    private SmsUtil smsUtil;

    @Autowired
    public MemberSubscribeServiceImpl(MemberSubscribeRepository memberSubscribeRepository) {
        super(memberSubscribeRepository);
        this.memberSubscribeRepository = memberSubscribeRepository;
    }

    @Override
    public Page<MemberSubscribeDetailDto> listMemberSubscribe(MemberSubscribeQueryDto queryDto, Pageable pageable) {
        String searchStr = queryDto.getSearchStr();
        Query query = new Query().addCriteria(Criteria.where("corporationCode").is(queryDto.getCorporationCode()));
        if (StringUtils.isNotEmpty(queryDto.getCityCode())) {
            query.addCriteria(Criteria.where("cityCode").is(queryDto.getCityCode()));
        } else if (!CollectionUtils.isEmpty(queryDto.getCityCodes())){
            query.addCriteria(Criteria.where("cityCode").in(queryDto.getCityCodes()));
        }
        if (queryDto.getBeginDate() != null && queryDto.getEndDate() != null) {
            query.addCriteria(Criteria.where("subscribeTime").gte(queryDto.getBeginDate()).lt(queryDto.getEndDate()));
        }
        if (StringUtils.isNotBlank(queryDto.getSubscribeStatus())) {
            query.addCriteria(Criteria.where("subscribeStatus").is(queryDto.getSubscribeStatus()));
        }
        if (StringUtils.isNotEmpty(searchStr)) {
            Criteria criteria = new Criteria();
            criteria.orOperator(Criteria.where("memberName").regex(".*?" + searchStr + ".*"),
                    Criteria.where("memberPhone").regex(".*?" + searchStr + ".*"),
                    Criteria.where("subscribePhone").regex(".*?" + searchStr + ".*"),
                    Criteria.where("estateName").regex(".*?" + searchStr + ".*"));
            query.addCriteria(criteria);
        }
        long count = mongoTemplate.count(query.with(pageable), MemberSubscribe.class);
        List<MemberSubscribe> list = new LinkedList<>();
        if (count > 0) {
            list = mongoTemplate.find(query.with(pageable), MemberSubscribe.class);
        }

        return PageableExecutionUtils.getPage(memberSubscribeMapper.domainToDetailDto(list), pageable, () -> count);
    }

    @Override
    public void updateSubscribeStatus(UpdateSubscribeStatusDto updateSubscribeStatusDto) {
        MemberSubscribe memberSubscribe = new MemberSubscribe();
        memberSubscribe.setId(updateSubscribeStatusDto.getId());
        memberSubscribe.setSubscribeStatus(updateSubscribeStatusDto.getSubscribeStatus());
        memberSubscribe.setSubscribeTime(new Date());
        updateById(memberSubscribe);
    }

    @Override
    public MemberSubscribe saveByParams(MemberSubscribeSaveDto saveDto, String subscribeStatus) {
        //先删除后添加
        deleteByMemberIdAndEstateUniqueUuid(saveDto.getMemberId(), saveDto.getEstateUniqueUuid());

        MemberSubscribe params = new MemberSubscribe();
        BeanUtils.copyProperties(saveDto, params);
        params.setCorporationCode(QfContextHolder.getContext().getCorporationCode());
        params.setSubscribeStatus(subscribeStatus);
        params.setSubscribeTime(new Date());
        params.setDeleted(false);
        params.setIsMessage(0);
        Optional<Member> memberOptional = memberService.findById(saveDto.getMemberId());
        if (memberOptional.isPresent()) {
            Member member = memberOptional.get();
            params.setMemberName(member.getName());
            params.setMemberPhone(member.getMobilePhone());
        }
        return memberSubscribeRepository.insert(params);
    }

    @Override
    public Page<MemberSubscribe> findEstateUniqueUuidListByParams(MemberSubscribeQueryDto queryDto, Pageable pageable) {
        Query query = new Query();

        QfContext qfContext = QfContextHolder.getContext();

        Criteria criteria = Criteria.where("corporationCode").is(qfContext.getCorporationCode());

        query.addCriteria(criteria);

        criteria.and("subscribeStatus").is(SubscribeConstants.ADD_SUBSCRIBE.getValue());
        criteria.and("deleted").is(false);

        if (StringUtils.isNotBlank(queryDto.getMemberId())) {
            criteria.and("memberId").is(queryDto.getMemberId());
        }

        // 拼分页参数
        PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.Direction.DESC, "subscribeTime");
        query.with(pageRequest);

        long count = mongoTemplate.count(query, MemberSubscribe.class);
        List<MemberSubscribe> result = new ArrayList<>();
        if (count > 0) {
            result = mongoTemplate.find(query, MemberSubscribe.class);
        }

        return PageableExecutionUtils.getPage(result, pageable, () -> count);
    }

    @Override
    public List<MemberSubscribe> findEstateUniqueUuidListByParams(MemberSubscribeQueryDto queryDto) {
        Query query = new Query();

        QfContext qfContext = QfContextHolder.getContext();

        Criteria criteria = Criteria.where("corporationCode").is(qfContext.getCorporationCode());

        criteria.and("subscribeStatus").is(SubscribeConstants.ADD_SUBSCRIBE.getValue());
        criteria.and("deleted").is(false);

        query.addCriteria(criteria);
        query.with(Sort.by(Sort.Order.desc("subscribeTime")));

        if (StringUtils.isNotBlank(queryDto.getMemberId())) {
            criteria.and("memberId").is(queryDto.getMemberId());
        }
        return mongoTemplate.find(query, MemberSubscribe.class);
    }

    @Override
    public MemberSubscribe findByMemberIdAndEstateUniqueUuid(String memberId, String estateUniqueUuid) {
        return memberSubscribeRepository.findFirstByMemberIdAndEstateUniqueUuidAndDeletedAndCorporationCode(memberId, estateUniqueUuid, false, QfContextHolder.getContext().getCorporationCode());
    }

    @Override
    public void deleteByMemberIdAndEstateUniqueUuid(String memberId, String estateUniqueUuid) {
        MemberSubscribe m = findByMemberIdAndEstateUniqueUuid(memberId, estateUniqueUuid);
        if (m != null) {
            m.setDeleted(true);
            updateById(m);
        }
    }

    @Override
    public void sendMessagesTask(String corporationCode) {

        //当前楼盘符合条件的列表
        List<MemberSubscribe> memberSubscribeList = memberSubscribeRepository.findAllByCorporationCodeAndIsMessageAndDeleted(corporationCode, 0, false);
        if (CollectionUtils.isEmpty(memberSubscribeList)) {
            return;
        }

        Query query = new Query();
        Criteria criteria = Criteria.where("corporationCode").is(corporationCode);
        criteria.and("openDate").lte(new Date());
        criteria.and("deleted").is(false);
        query.addCriteria(criteria);
        //今日开盘的楼盘(不一定有人订阅)
        List<FirsthandEstate> firsthandEstates = mongoTemplate.find(query, FirsthandEstate.class);
        log.info("今天开盘的楼盘：{}", JSONObject.toJSONString(firsthandEstates));
        if (CollectionUtils.isEmpty(firsthandEstates)) {
            return;
        }
        List<String> smsList = firsthandEstates.stream().map(FirsthandEstate::getEstateUniqueUuid).collect(Collectors.toList());

        //符合发送短信的楼盘uuid
        List<MemberSubscribe> resultList = memberSubscribeList.stream().filter(f -> smsList.contains(f.getEstateUniqueUuid())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(resultList)) {
            return;
        }
        log.info("发送开盘提醒短信的订阅列表：{}", JSONObject.toJSONString(resultList));
        Corporation corporation = corporationService.getCorporationByCorporationCode(corporationCode);
        SmsDto smsDto = getSmsDto(corporation);
        smsDto.setTemplateId("DKHxcx");
        //您订阅的楼盘【{1}】已开盘，请您进入{2}小程序进行查看和咨询。
        for (MemberSubscribe memberSubscribe : resultList) {
            smsDto.setMobiles(Arrays.asList(memberSubscribe.getSubscribePhone()));
            Map<String, Object> templateParam = new HashMap<>(2);
            templateParam.put("key1", memberSubscribe.getEstateName());
            templateParam.put("key2", corporation.getMiniName());
            smsDto.setTemplateParam(templateParam);
            if (smsUtil.sendSms(smsDto)) {
                log.info("发送验证码成功，mobilePhone:{},text:{}", memberSubscribe.getMemberPhone(), JSONObject.toJSONString(templateParam));
                //修改ismessage = 1
                memberSubscribe.setIsMessage(1);
                updateById(memberSubscribe);
            }
        }
    }

    private SmsDto getSmsDto(Corporation corporation) {
        List<SmsPlatformConfig> list = corporation.getSmsPlatformConfig();
        if (CollectionUtils.isEmpty(list)) {
            throw new BusinessException("集团未配置短信模版信息");
        }
        SmsPlatformConfig smsConfig = list.get(0);
        return SmsDto.builder()
                .url(smsConfig.getUrl())
                .token(smsConfig.getToken())
                .secret(smsConfig.getSecret())
                .mainAccountCode(smsConfig.getMainAccountCode())
                .subAccountCode(smsConfig.getSubAccountCode())
                .templateId(smsConfig.getTemplateId())
                .build();
    }
}
